/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2021年11月1日
 */
package com.massyframework.beanskin.runtime.framework.installing.classloading;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLStreamHandler;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Set;

import com.massyframework.beanskin.ModuleIdentifier;
import com.massyframework.beanskin.util.classloading.LocalResourcesPath;
import com.massyframework.beanskin.util.classloading.ModuleClassLoader;
import com.massyframework.beanskin.util.classloading.ResourceLocateFilterRepository;

/**
 * 支持热部署的类加载器
 * @author huangkh
 *
 */
public class HotDeploymentableClassLoader extends ModuleClassLoader {
	
	private static final String PROTOCAL = "proxy";
	
	/**
	 * 构造方法
	 * @param builder {@link Builder}
	 */
	protected HotDeploymentableClassLoader(Builder builder) {
		super(builder);
	}
		
	@Override
	protected Enumeration<URL> findResourcesWithUcp(String name) throws IOException {
		return this.requireHotDeployment() ?
				new URLEnumeration(super.findResourcesWithUcp(name), this::trasformToProxyURL) :
				super.findResourcesWithUcp(name);
	}


	@Override
	protected URL findResourceWithUcp(String name) {
		URL result = super.findResourceWithUcp(name);
		if (this.requireHotDeployment()) {
			if (result != null) {
				result = this.trasformToProxyURL(result);
			}
		}
		return result;
	}


	/**
	 * 转化为代理URL
	 * @param url {@link URL}
	 * @return {@link URL}
	 * @throws MalformedURLException
	 */
	protected URL trasformToProxyURL(URL url) {
		if (url == null) return null;
		
		try {
			URLStreamHandler handler = new URLStreamHandlerProxy(url);
			return new URL(PROTOCAL, url.getHost(), url.getPort(), url.getFile(), handler);
		}catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 创建构建器实例
	 * @return {@link Builder}
	 */
	public static Builder newBuilder() {
		return new Builder();
	}

	public static class Builder extends ModuleClassLoader.Builder {

		@Override
		public Builder certificate(String name, String data) {
			super.certificate(name, data);
			return this;
		}

		@Override
		public Builder decryptClassNames(Set<String> value) {
			super.decryptClassNames(value);
			return this;
		}
		
		

		@Override
		public Builder decryptScriptFileNames(Set<String> value) {
			super.decryptScriptFileNames(value);
			return this;
		}

		@Override
		public Builder publicKey(String value) {
			super.publicKey(value);
			return this;
		}

		@Override
		public Builder addLocalResourcesPath(
				LocalResourcesPath value) {
			super.addLocalResourcesPath(value);
			return this;
		}

		@Override
		public Builder addLocalResourcesPaths(
				Collection<LocalResourcesPath> value) {
			super.addLocalResourcesPaths(value);
			return this;
		}

		@Override
		public Builder addURL(URL url) {
			super.addURL(url);
			return this;
		}

		@Override
		public Builder addURLs(Collection<URL> urls) {
			super.addURLs(urls);
			return this;
		}

		@Override
		public Builder hotDeployment(boolean value) {
			super.hotDeployment(value);
			return this;
		}

		@Override
		public Builder parentClassLoader(
				ClassLoader value) {
			super.parentClassLoader(value);
			return this;
		}
		
		@Override
		public Builder resourceLocateFilterRepository(ResourceLocateFilterRepository value) {
			super.resourceLocateFilterRepository(value);
			return this;
		}

		@Override
		public Builder moduleIdentifier(
				ModuleIdentifier value) {
			super.moduleIdentifier(value);
			return this;
		}

		@Override
		public HotDeploymentableClassLoader build() {
			return new HotDeploymentableClassLoader(this);
		}
		
		
	}
}
